﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Dreamz
{
    // Contains information about users location in game, inventory and which commands the user can use during game.
    [Serializable()]
    public class Player
    {
        public int X, Y;
        public Room CurrentRoom
        {
            get { return GameEngine.S.World[X, Y]; }
        }
        public Room PreviousRoom;
        public Dictionary<string, Item> Inventory;

        public Player()
        {
            Inventory = new Dictionary<string, Item>();
        }

        // Checks if item asked for exists in inventory or not.
        public bool HasItem(string Name)
        {
            
            bool found = false;
            foreach (Item item in Inventory.Values)
            {
                foreach (string name in item.Names)
                    if (name.ToLower() == Name.ToLower())
                        found = true;
                if (found)
                    return true;
            }

            return false;
        }
        // Checks if item asked for exists in inventory or not, and returns found item using out. 
        public bool HasItem(string Name, out Item Item)
        {
            Item = null;
            bool found = false;
            foreach (Item item in Inventory.Values)
            {
                foreach (string name in item.Names)
                {
                    if (name.ToLower() == Name.ToLower())
                        found = true;
                }
                if (found)
                {
                    Item = item;
                    return true;
                }
            }

            return false;
        }

        // Outputs descriptions of items in the game
        public void Look(string Args)
        {
            // if look is used on inventory, list items in inventory
            if (Args == "inventory" || Args == "inv")
            {
                string itemstring = "Inventory:";
                foreach (Item item in Inventory.Values)
                    itemstring += "\n" + item.Names[0];
                UI.Console.Write(itemstring, ConsoleColor.Cyan);
            }
            else
            {
                Item item;
                if (HasItem(Args, out item))
                {
                    UI.Console.Write(item.Description);
                    if (item.OnLook != null)
                        item.OnLook();
                }
                else if (CurrentRoom.HasItem(Args, out item))
                {
                    UI.Console.Write(item.Description);
                    if (item.OnLook != null)
                        item.OnLook();
                }
                else
                {
                    UI.Console.Write("Stop this gibberish!");
                }
            }
        }

        // This is the method for the 'go' command. Used for moving around in the world
        public void Go(string Args)
        {
            PreviousRoom = CurrentRoom;

            switch (Args)
            {
                case "north":
                case "n": if (CurrentRoom.North) { ++Y; Leave(Direction.North); } break;
                case "east":
                case "e": if (CurrentRoom.East) { ++X; Leave(Direction.East); } break;
                case "south":
                case "s": if (CurrentRoom.South) { --Y; Leave(Direction.South); } break;
                case "west":
                case "w": if (CurrentRoom.West) { --X; Leave(Direction.West); } break;
            }

            if (CurrentRoom.OnEnter != null)
                CurrentRoom.OnEnter();
            if (CurrentRoom.OnArrival != null)
                CurrentRoom.OnArrival();

            UI.Console.Clear();
        }
        void Leave(Direction direction)
        {
            PreviousRoom.IsVisited = true;
            if (PreviousRoom.OnLeave != null)
                PreviousRoom.OnLeave(direction);
        }

        // This is the method for the 'use' command
        public void Use(string Args)
        {
            if (Args.Length > 0)
            {
                string itemName = Args;
                Item item;
                if (HasItem(itemName, out item))
                {
                    if (item.OnUse != null)
                        item.OnUse();
                    else
                    {
                       UI.Console.Write("Stop this gibberish!");
                    }
                }
                else if (CurrentRoom.HasItem(itemName, out item))
                {
                   if (item.OnUse != null)
                      item.OnUse();
                   else
                   {
                      UI.Console.Write("Stop this gibberish!");
                   }
                }
                else
                {
                   UI.Console.Write("Stop this gibberish!");
                }
          }
        }

        // This is the method for the 'take' command
        public void Take(string Args)
        {
            if (Args.Length > 0)
            {
                string itemName = Args;
                Item item;

                if (HasItem(itemName))
                        UI.Console.WriteLine("You already have that in your inventory");
                else if (CurrentRoom.HasItem(itemName, out item))
                {
                    if (item.CanPickUp)
                    {
                        Inventory.Add(item.Names[0].ToLower(), item);
                        CurrentRoom.Items.Remove(item.Names[0].ToLower());
                        if (Inventory[item.Names[0].ToLower()].OnTake != null)
                            Inventory[item.Names[0].ToLower()].OnTake();
                        UI.Console.WriteLine("You put the " + Inventory[item.Names[0].ToLower()].Names[0] + " in your inventory");
                    }
                    else
                        UI.Console.Write("You can't pick that up, silly!");
                }
                else
                {
                   UI.Console.Write("Stop this gibberish!");
                }
            }
        }

        // This is the method for the 'TP' command, a command used in testing.
        public void TP(string Args)
        {
            try
            {
                int x = int.Parse(Args.Substring(0, 1));
                int y = int.Parse(Args.Substring(1, 1));

                X = x;
                Y = y;
            }
            catch (Exception)
            {
                UI.Console.Write("Stop this gibberish!");
            }
        }
    }
}
